/*! \page license
 *
 * Copyright (c) 2011, Blaise Lengrand
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list
 * of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this
 * list of conditions and the following disclaimer in the documentation and/or
 * other materials provided with the distribution.
 * Neither the name of `snWin' nor the names of its contributors may be used to
 * endorse or promote products derived from this software without specific prior
 * written permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
var facebook_access_token = null;
var facebook_id_stack = new Array();
var facebook_entries = new Array();

const facebook_feed = {
  'display_name': "Facebook",
  'author': "Blaise Lengrand",
  'id': "facebook",
  'default_color': "#123456",
  'ep': {
    'connect': facebook_connect,
    'is_connected': facebook_is_connected,
    'update': facebook_update,
    'previous': facebook_previous,
    'like': facebook_like,
    'comment': facebook_comment,
    'publish': facebook_publish,
    'refresh': facebook_refresh,
    'add_fields': facebook_add_fields,
    'share': facebook_share,
    'share_format': facebook_share_format
  },
  // Extra parameters with their default values (will be saved in the session)
  'session': {
    'session': null,
  },
  'options': {
    'refresh_entry': true,
    'compare_entry_content': true
  },
  'update_rate_s': 20
};

//! Add the feed to the list
feed_available[facebook_feed.id] = facebook_feed;

function facebook_is_connected(feed_id)
{
  if (feed[feed_id].session.session)
    return true;
  return false;
}

function facebook_connect(feed_id, context)
{
  // Registers the feed
  feed_register(feed_id, facebook_feed, context);

  feed_log("Connecting", feed_id);

  // Create array for new/previous entries lookup
  facebook_entries[feed_id] = {
    'new': null,
    'previous': null
  };
  // Push the ID onto the stack to retrieve it later
  facebook_id_stack.push(feed_id);
  // If there is no session
  if (!context.session)
  {
    feed_log("No session available, will create one", feed_id);
    var url = "system/pages/social/facebook/facebook_connect.php?new=1";
    if (typeof debug != "undefined")
      url += "&debug=1";
    feed_iframe(url, "90%", "90%");
  }
  else
    facebook_access_token_set(context.session);
}

//! Function called once the connection with Facebook is completed
function facebook_access_token_set(access_token)
{
  // Get the oldest ID pushed onto the stack
  feed_id = facebook_id_stack.shift();

  feed_log("Session acquired `" + access_token + "'", feed_id);

  // Close the login window
  feed_prompt_close();
  // Save the session
  feed[feed_id].session.session = access_token;
  feed_connected(feed_id);

  feed_log("Feed connected", feed_id);
}

function facebook_previous(feed_id)
{
  var url = null;
  feed_log("Get previous feed", feed_id);
  if (facebook_entries[feed_id].previous)
    url = "https://graph.facebook.com/me/home?date_format=U&access_token=" + feed[feed_id].session.session + "&limit=5&callback=?" + "&until=" + facebook_entries[feed_id].previous;
  facebook_get_feed(url, false, feed_id);
}

function facebook_update(feed_id)
{
  var url = null;
  if (facebook_entries[feed_id].new)
    url = "https://graph.facebook.com/me/home?date_format=U&access_token=" + feed[feed_id].session.session + "&limit=5&callback=?" + "&since=" + facebook_entries[feed_id].new;

  feed_log("Get new feed", feed_id);
  facebook_get_feed(url, true, feed_id);
}

function facebook_refresh(feed_id, entry)
{
  // Makes sure the entry has an ID
  if (!entry.extra["facebook"] || !entry.extra["facebook"].object_id)
    return feed_log("No ID available for this entry", feed_id, "error");
  url = "https://graph.facebook.com/" + entry.extra["facebook"].object_id + "?date_format=U&access_token=" + feed[feed_id].session.session + "&limit=5&callback=?";
  // Updates the new entry
  facebook_get_feed(url, true, feed_id);
}

function facebook_get_feed(url, is_new, feed_id)
{
  base_url = "https://graph.facebook.com/me/home?date_format=U&access_token=" + feed[feed_id].session.session + "&limit=5&callback=?";
  if (!url)
    url = base_url;
  url = url.replace(/callback=[^&]*&/i, "callback=?&");
  feed_log("Feed url `" + url + "'", feed_id);
  feed_get_json(feed_id, url, function(data) {
    // Field required
    var date_max = (facebook_entries[feed_id].new)?facebook_entries[feed_id].new:0;
    var date_min = (facebook_entries[feed_id].previous)?facebook_entries[feed_id].previous:feed_current_time();

    // If data is an object with a data element, remove it
    if (data && data.data)
      data = data.data;
    // If data is an object, it should be casted to an Array for compatibility
    if (typeof(data.length) == 'undefined')
      data = new Array(data);
    // Check if some data are available, if not returns
    if (!data)
    {
      feed_log("No data available", feed_id);
      return feed_callback(feed_id);
    }

    var nb_new_entries = 0;
    $.each(data, function(i, item) {
      var name = "";
      var picture = "";
      var icon = "";
      var message = "";
      var link = "";
      var extra = new Array();
      var id = null;

      // Creates an extra object to contain facebook specific data
      extra["facebook"] = new Object();

      // Increase the number of new entries
      nb_new_entries++;

      // Applies default values to 'extra' because sometimesit is not present on the requests
      if (item.id)
      {
        var temp = item.id.split("_", 2);
        extra["comment"] = {
          'nb': 0,
          'link': "http://www.facebook.com/" + temp[0] + "/posts/" + temp[1],
          'data': null
        };
        extra["like"] = {
          'nb': 0,
          'link': "http://www.facebook.com/" + temp[0] + "/likes/" + temp[1]
        };
        extra["facebook"].object_id = item.id;
        // Build the ID
        id = "facebook_" + item.id;
      }

      if (item.from && item.from.name)
      {
        if (item.from.id)
          name += "<a href=\"http://www.facebook.com/profile.php?id=" + item.from.id + "\">";
        name += item.from.name;
        if (item.from.id)
          name += "</a>";
      }
      if (item.to && item.to.data)
      {
        extra["to"] = "";
        for (i=0; i<item.to.data.length; i++)
        {
          if (item.to.data[i] && item.to.data[i].name)
          {
            if (i)
              extra["to"] += ", ";
            str = item.to.data[i].name;
            if (item.to.data[i].id)
              str = "<a href=\"http://www.facebook.com/profile.php?id=" +item.to.data[i].id + "\">" + str + "</a>";
            extra["to"] += str;
          }
        }
      }
      if (item.from && item.from.id)
        picture = 'http://graph.facebook.com/' + item.from.id + '/picture';
      if (item.link)
        var link = item.link;
      if (item.icon)
        var icon = item.icon;
      var date = item.created_time;
      date_min = Math.min(date, date_min);
      date_max = Math.max(date, date_max);
      // Process message
      message = facebook_format_message(item, id, extra);
      // Extra
      if (item.application && item.application.name)
        extra["date_after_text"] = { 'text': " via " + item.application.name };
      //      if (item.actions)
      // {
      //for (i in item.actions)
      //{
      //  switch (item.actions[i].name)
      //  {

          if (item.comments)
          {
            var nb = 0;
            var comment_link = null;
            var data = new Array();
            if (item.comments)
            {
              if (item.comments.count)
                nb = item.comments.count;
              for (j in item.comments.data)
              {
                var comment = item.comments.data[j];
                var comment_name = "";
                if (comment.from)
                {
                  if (comment.from.id)
                    comment_name += "<img src=\"http://graph.facebook.com/" + comment.from.id + "/picture\"/><a href=\"http://www.facebook.com/profile.php?id=" + comment.from.id + "\">";
                  if (comment.from.name)
                    comment_name += comment.from.name;
                  if (comment.from.id)
                    comment_name += "</a>";
                }
                data[j] = {
                  'name': comment_name,
                  'text': (comment.message)?comment.message:"",
                  'date': (comment.created_time)?(comment.created_time):0
                };
              }
            }
            extra["comment"].nb = nb;
            extra["comment"].data = data;
            // If no comments link, remove the feature
            //if (!item.actions[i].link)
            //   extra["comment"].link = null;
          }
          if (item.likes)
          {
            var nb = 0;
            var like_link = null;
            if (item.likes && item.likes.count)
              nb = item.likes.count;
            extra["like"].nb = nb;
            // If not like link, remove the feature
            //if (!item.actions[i].link)
            //  extra["like"].link = null;
            // Tooltip information
            if (item.likes && item.likes.data)
            {
              var str = "";
              for (i=0; i<item.likes.data.length; i++)
              {
                if (i)
                  str += ", ";
                if (item.likes.data[i] && item.likes.data[i].name)
                  str += item.likes.data[i].name;
              }
              if (item.likes.data.length < nb)
                str += ", ...";
            }
            extra["like"].tooltip = str;
           }
          /*
        }
      }
          */
      // Add the entry if it is valid (at least a creation date and a name)
      if (date && name)
      {
        feed_entry_add({
          'id': id,
          'name': name,
          'picture': picture,
          'message': message,
          'link': link,
          'date': date,
          'icon': icon,
          'extra': extra
        }, feed_id);
      }
    });
    // Set new entries pointer
    //if (data.paging && data.paging.previous && (is_new || !facebook_entries[feed_id].new))
    facebook_entries[feed_id].new = date_max; // Fix a bug in Facebook API - data.paging.previous;
    //if (data.paging && data.paging.next && (!is_new || !facebook_entries[feed_id].previous))
    facebook_entries[feed_id].previous = date_min; // Fix a bug in Facebook API - data.paging.next;
    // If the action is a previous command and there are no new feeds, then inform the feed_core
    if (!nb_new_entries && !is_new)
      feed_callback(feed_id);
    else
    // Tell the core module that the feed is acquired
      feed_callback(feed_id);
  },
  function() {
    feed_callback(feed_id);
  });
}

function facebook_format_message(item, id, extra)
{
  var is_table = false;

  text = "";
  if (item.message)
    text += item.message;

  if (item.picture || item.link || item.name || item.caption || item.description)
    is_table = true;

  if (is_table)
    text += "<table style=\"width: 450px; color: #777777;\"><tr>";
  if (item.picture)
  {
    var id_selector = "id_facebook_sel_" + item.id;
    text += "<td valign=\"top\">";
    link = "";
    if (item.source)
    {
      extra["embedded_iframe"] = {
        'obj_jq_selector': "#" + id_selector,
        'src': item.source
      };
    }
    else if (item.link)
      text += "<a href=\"" + item.link + "\">";
    text += "<img id=\"" + id_selector + "\" style=\"max-width: 150px;\" src=\"" + item.picture + "\" />";
    if (!item.source && item.link)
      text += "</a>"
    text += "</td>";
  }
  if (is_table)
    text += "<td valign=\"top\" width=\"100%\">";
  if (item.link)
    text += "<a href=\"" + item.link + "\">";
  if (item.name)
  {
    extra["facebook"].name = item.name;
    text += item.name;
  }
  else if (item.link)
    text += item.link;
  if (item.link)
    text += "</a>";
  if (item.link || item.name)
    text += "<br />";
  if (item.caption)
  {
    extra["facebook"].caption = item.caption;
    text += "<span style=\"font-size: 11px;\">" + item.caption + "</span><br />";
  }
  if (item.description)
  {
    extra["facebook"].description = item.description;
    text += "<p style=\"margin-top: 5px; margin-bottom: 5px;\">" + item.description + "</p>";
  }
  for (i in item.properties)
  {
    var prop = item.properties[i];
    if (prop.name)
      text += prop.name + ": ";
    if (prop.href)
      text += "<a class=\"message_link\" href=\"" + prop.href + "\">";
    if (prop.text)
      text += prop.text;
    if (prop.href)
      text += "</a>";
    text += "<br />";
  }
  if (is_table)
    text += "</td></table>";

  return text;
}

function facebook_action(type, feed_id, entry, url, extra)
{
  feed_log("Posting `" + type + "'...", feed_id);
    feed_post(feed_id, "system/pages/social/facebook/facebook_action.php", "access_token=" + feed[feed_id].session.session + "&type=" + type + "&url=" + escape(url) + ((extra)?("&" + extra):""),
    function(data) {
      feed_callback(feed_id);
    },
    function() {
      feed_log("Error sending the request", feed_id, "error");
      feed_callback(feed_id, true);
    }
  );
}

function facebook_like(feed_id, entry)
{
  var url = null;

  // Makes sure the like link exists
  if (!entry.extra["facebook"] || !entry.extra["facebook"].object_id)
    return feed_log("No ID available for this entry", feed_id, "error");
  url = "https://graph.facebook.com/" + entry.extra["facebook"].object_id + "/likes";

  facebook_action("like", feed_id, entry, url);
}

function facebook_comment(feed_id, entry, message)
{
  var url = null;

  // Makes sure the comment link exists
  if (!entry.extra["facebook"] || !entry.extra["facebook"].object_id)
    return feed_log("No ID available for this entry", feed_id, "error");
  url = "https://graph.facebook.com/" + entry.extra["facebook"].object_id + "/comments";

  facebook_action("comment", feed_id, entry, url, "message=" + message);
}

function facebook_publish(feed_id, message)
{
  var link = "";
  var url = "https://graph.facebook.com/me/feed";

  if (link = feed_find_link(message))
    facebook_action("publish", feed_id, null, url, "message=" + message + "&link=" + link);
  else
    facebook_action("publish", feed_id, null, url, "message=" + message);
}

function facebook_share_format(feed_id, entry, share_info)
{
  if (!entry.extra['facebook'])
    feed_log("This is not a facebook feed entry", feed_id, "error");
  if (entry.extra['facebook'].name)
    share_info.title = entry.extra['facebook'].name;
  if (entry.extra['facebook'].description)
    share_info.message = entry.extra['facebook'].description;
  // If it is a status
  if (!entry.extra['facebook'].name && !entry.extra['facebook'].description)
    share_info.picture = feed_host_url() + "system/pages/social/facebook/facebook_proxy.php?f=" + escape(entry.picture);
}

// If the image is from facebook, cannot share facebook images anymore:
// "We no longer allow stream stories to contain images that are hosted on the fbcdn.net domain.
// The images associated with these URLs aren't always optimized for stream stories and occasionally
// resulted in errors, leading to a poor user experience. Make sure your stream attachments don't
// reference images with this domain. You should host the images locally"
function facebook_is_valid_link(url)
{
  if ($.url.parse(url).host.match(/fbcdn.net$/))
    return false;
  return true;
}

function facebook_share(feed_id, entry, share_info)
{
  var url = "https://graph.facebook.com/me/feed";
  var query = "";

  var link = (entry.link)?entry.link:"http://www.snwin.com";
  query += "link=" + escape(link);

  // Test if there is a picture to share
  if (share_info.picture)
  {
    if (!facebook_is_valid_link(share_info.picture))
      share_info.picture = null;
    if (share_info.picture)
      query += "&picture=" + escape(share_info.picture);
  }

  // If the source feed entry has a embedded video
  if (entry.extra && entry.extra["embedded_iframe"] && entry.extra["embedded_iframe"].src)
  {
    var source = entry.extra["embedded_iframe"].src;
    if (facebook_is_valid_link(source))
    {
      query += "&source=" + escape(source);
      // Picture is mandatory, so if no picture for the embedeed flash link, then use a black default picture
      if (!share_info.picture)
        query += "&picture=" + feed_host_url() + "system/pages/social/facebook/empty.png";
    }
  }

  // Link
  if (share_info.link)
    query += "link=" + escape(share_info.link);

  // If the host entry is from facebook and a link is present, then avoid all the work made before and share only the link
  if (entry.extra && entry.extra["facebook"] && entry.link)
    query = "link=" + escape(entry.link);

  query += "&name=" + escape(share_info.title);
  query += "&caption=" + escape($.url.parse(link).host);
  query += "&description=" + escape(share_info.message);
  query += "&message=" + escape(share_info.comment);

  facebook_action("share", feed_id, null, url, query);
}

function facebook_add_fields()
{
  if (typeof debug != "undefined" && debug)
  {
    var div_access_token = document.createElement("div");
    $(div_access_token).append("access_token ");
    var input_access_token = document.createElement("input");
    input_access_token.setAttribute("name", "session");
    input_access_token.setAttribute("type", "text");
    div_access_token.appendChild(input_access_token);
    return div_access_token;
  }
  return null;
}